//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;

namespace Eas.WebCrawler.Test.Scenario {

    public enum ThrowFor {
        None,
        CreateWebRequest,
        ResponseIsText,
        BeginReadStream,
        EndRead,
        BeginGetResponse,
        EndGetResponse,
        GetRedirectUri,
        GetResponseCode,
        GetResponseStream,
        IsRedirect
    };

    public class TestGateway : Eas.WebCrawler.Model.Gateway.BaseWebGateway{
        public static Dictionary<Uri, object> _BinaryUris = new Dictionary<Uri, object>();
        public static Dictionary<Uri, Uri> _RedirectUris = new Dictionary<Uri, Uri>();
        public static ThrowFor _ThrowFor = ThrowFor.None;
        public static bool _ThrowWebException = false;
        public static int _ErrorCount = 0;
        public int _ReadSleepTime = 0;
        public int _GetResponseSleepTime = 0;

        public static void Clear() {
            _ErrorCount = 0;
            _ThrowFor = ThrowFor.None;
            _ThrowWebException = false;
            _BinaryUris.Clear();
            _RedirectUris.Clear();
        }

        private void Throw(ThrowFor throwFor) {
            if (throwFor != _ThrowFor) return;

            if (_ErrorCount == 0)
                _ThrowFor = ThrowFor.None;
            else {
                --_ErrorCount;
            }

            if (_ThrowWebException)
                throw new System.Net.WebException("Test Injected Failure.", System.Net.WebExceptionStatus.ProtocolError);
            else
                throw new System.Exception("Test Injected Failure.");
        }

        public override Eas.WebCrawler.Interfaces.WebRequestInterface CreateWebRequest(Eas.WebCrawler.Interfaces.ProcessingState processingState) {
            Uri newUri = UriMap.Get(processingState.Request.Uri);
            return base.CreateWebRequest(processingState);
        }

        public override bool ResponseIsText(Eas.WebCrawler.Interfaces.ProcessingState processingState) {
            return !_BinaryUris.ContainsKey(processingState.Request.Uri);
        }

        public override IAsyncResult BeginGetResponse(Eas.WebCrawler.Interfaces.ProcessingState processingState, AsyncCallback callback, object state) {
            if (this._GetResponseSleepTime > 0) {
                EventHandler handler = (EventHandler)delegate(object sender, EventArgs a) { System.Threading.Thread.Sleep(_GetResponseSleepTime); };
                return handler.BeginInvoke(null, System.EventArgs.Empty, callback, state);
            }

            Throw(ThrowFor.BeginGetResponse);
            return base.BeginGetResponse(processingState, callback, state);
        }

        public override IAsyncResult BeginReadStream(Eas.WebCrawler.Interfaces.ProcessingState processingState, byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
            if (this._ReadSleepTime > 0) {
                EventHandler handler = (EventHandler)delegate(object sender, EventArgs a) { System.Threading.Thread.Sleep(_ReadSleepTime); };
                return handler.BeginInvoke(null, System.EventArgs.Empty, callback, state);
            }
            Throw(ThrowFor.BeginReadStream);
            return base.BeginReadStream(processingState, buffer, offset, count, callback, state);
        }

        public override Eas.WebCrawler.Interfaces.WebResponseInterface EndGetResponse(Eas.WebCrawler.Interfaces.ProcessingState processingState, IAsyncResult result) {
            Throw(ThrowFor.EndGetResponse);
            return base.EndGetResponse(processingState, result);
        }

        public override int EndReadStream(Eas.WebCrawler.Interfaces.ProcessingState processingState, IAsyncResult result) {
            Throw(ThrowFor.EndRead);
            return base.EndReadStream(processingState, result);
        }

        public override Uri GetRedirectUri(Eas.WebCrawler.Interfaces.ProcessingState processingState) {
            Throw(ThrowFor.GetRedirectUri);
            if (_RedirectUris.ContainsKey(processingState.Request.Uri))
                return _RedirectUris[processingState.Request.Uri];
            return base.GetRedirectUri(processingState);
        }

        public override int GetResponseCode(System.Net.WebException exception) {
            Throw(ThrowFor.GetResponseCode);
            return base.GetResponseCode(exception);
        }

        public override System.IO.Stream GetResponseStream(Eas.WebCrawler.Interfaces.ProcessingState processingState) {
            Throw(ThrowFor.GetResponseStream);
            return base.GetResponseStream(processingState);
        }

        public override bool IsRedirect(Eas.WebCrawler.Interfaces.ProcessingState processingState) {
            Throw(ThrowFor.IsRedirect);
            if (_RedirectUris.ContainsKey(processingState.Request.Uri))
                return true;

            return base.IsRedirect(processingState);
        }
    }
}
